#include <GL/glut.h>
#include <iostream>
#include <stdlib.h>
#include "../include/Callbacks.h"
#include "../include/Image.h"
#include "../include/Masque.h"
#include "../include/Pixel.h"
#define GLUT_WHEEL_UP 3
#define GLUT_WHEEL_DOWN 4
int Callbacks::hauteur = 0;
int Callbacks::largeur = 0;
int Callbacks::MousePrevX = 0;
int Callbacks::MousePrevY = 0;
int Callbacks::modeDessin = 0;
Image* Callbacks::im = NULL;
Image* Callbacks::u = NULL;
Image* Callbacks::u1 = NULL;
Image* Callbacks::laplacien = NULL;
Image* Callbacks::laplacienU = NULL;
Masque* Callbacks::m = NULL;


void Callbacks::redim(int largeur, int hauteur)
{
	glViewport(0, 0, largeur, hauteur) ;
	glMatrixMode(GL_PROJECTION) ;
	glLoadIdentity() ;
	gluOrtho2D(0, largeur, 0, hauteur) ;
	glMatrixMode(GL_MODELVIEW) ;
	glLoadIdentity() ;
}

void Callbacks::souris (int bouton, int etat, int x, int y)
{
	switch (bouton)
	{
		case GLUT_LEFT_BUTTON:
			if (etat==GLUT_DOWN)
			{
				m->Dessine(x,hauteur-y,MousePrevX,MousePrevY,255);
				modeDessin = 0;
			}
			break ;
		case GLUT_RIGHT_BUTTON:
			if (etat==GLUT_DOWN)
			{
				m->Dessine(x,hauteur-y,MousePrevX,MousePrevY,0);
				modeDessin = 1;
			}
			break;
		case GLUT_WHEEL_UP:
			m->setTaillePinceau(m->getTaillePinceau()+1);
			break;
		case GLUT_WHEEL_DOWN:
			m->setTaillePinceau(m->getTaillePinceau()-1);
			break;
	}
	MousePrevX = x;
	MousePrevY = hauteur-y;
	glutPostRedisplay() ;
}

void Callbacks::mouvement(int x,int y){
	if(modeDessin)
		m->Dessine(x,hauteur-y,MousePrevX,MousePrevY,0);
	else
		m->Dessine(x,hauteur-y,MousePrevX,MousePrevY,255);
	MousePrevX = x;
	MousePrevY = hauteur-y;
	glutPostRedisplay() ;
}

void Callbacks::mouvementPassif(int x,int y){
	MousePrevX = x;
	MousePrevY = hauteur-y;
	glutPostRedisplay() ;
}

void Callbacks::traitementInit(){
	
	im = new Image();
	
	im->chargePPM("lena.ppm");
	laplacien = im->Laplacien();
	//laplacien->toSprite();
	//im->sauvePPM("parrot.ppm");
	im->toSprite();
	
	largeur = im->getL();
	hauteur = im->getH();
	m = new Masque(largeur,hauteur);
}
void Callbacks::traitement(){
	double lambda = 0.2,dt=0.5;	
	u1 = im->CopierImage();
	for(int nbIter = 0;nbIter <1000;nbIter++){
		delete u;
			u = u1->CopierImage();
		delete laplacienU;
		laplacienU = u->Laplacien();
		delete u1;
		u1 = new Image(largeur,hauteur);
		for(int y=0;y<hauteur;y++){
			for(int x=0;x<largeur;x++){
				int R = 1-m->LitBool(x,hauteur-y);//hauteur-y car les images sont stocké a l'envers du masque
				Pixel fp = im->LitPixel(x,y);
				Pixel up = u->LitPixel(x,y);
				Pixel ulp = laplacienU->LitPixel(x,y);
				Pixel tmp = (ulp*lambda + (fp-up)*(2.*R))*dt+up;
				u1->EcritPixel(x,y,tmp);
			}
		}
		//u1->toSprite();
		//u1->Afficher();
		//glutSwapBuffers();
		//std::cout<<nbIter<<std::endl;
	}
	u1->sauvePPM("test.ppm");
}

void Callbacks::affichage(void)
{
	glClear (GL_COLOR_BUFFER_BIT);
	im->Afficher();
	m->Afficher();
	m->AffichePinceau(MousePrevX,MousePrevY);
	glutSwapBuffers();
}

void Callbacks::clavier ( unsigned char key, int x, int y)
{
	Pixel t;
	switch (key)
	{
		case 'e' :
			m->Effacer();
			break;
		case ' ':
			traitement();
			break;
		case 'l':
			t = laplacien->LitPixel(x,y);
			std::cout<<t.getR()<<" "<<t.getV()<<" "<<t.getB()<<std::endl;
			break;
		case 27:
			delete im;
			delete u;
			delete u1;
			delete laplacien;
			delete laplacienU;
			delete m;
			exit(0);
			break;
        default:
       			break;
	}
	glutPostRedisplay();
}

void Callbacks::initGL(){

	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
	glEnable(GL_BLEND);
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	glutSetCursor(GLUT_CURSOR_NONE);
	
}
